home *** CD-ROM | disk | FTP | other *** search
-
-
-
- xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333)))) xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333))))
-
-
-
- NNNNAAAAMMMMEEEE
- _xxxx_tttt_aaaa_llll_kkkk______iiii_nnnn_tttt_rrrr______aaaa_llll_llll_oooo_cccc - allocate a XIO Interrupt channel
- _xxxx_tttt_aaaa_llll_kkkk______iiii_nnnn_tttt_rrrr______cccc_oooo_nnnn_nnnn_eeee_cccc_tttt - connect handling function
- _xxxx_tttt_aaaa_llll_kkkk______iiii_nnnn_tttt_rrrr______dddd_iiii_ssss_cccc_oooo_nnnn_nnnn_eeee_cccc_tttt - disconnect handling function
- _xxxx_tttt_aaaa_llll_kkkk______iiii_nnnn_tttt_rrrr______ffff_rrrr_eeee_eeee - release a XIO Interrupt channel
-
- SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
- #include <sys/XIO/xtalk.h>
-
- xtalk_intr_t
- xtalk_intr_alloc(vertex_hdl_t _v_h_d_l,
- device_desc_t _d_e_s_c,
- vertex_hdl_t _o_w_n_e_r)
-
- int
- xtalk_intr_connect(xtalk_intr_t _i_n_t_r,
- intr_func_t _f_u_n_c,
- intr_arg_t _a_r_g,
- xtalk_intr_setfunc_t _s_e_t_f_u_n_c,
- void *_s_e_t_f_u_n_c__a_r_g,
- void *_t_h_r_e_a_d)
-
- void
- xtalk_intr_disconnect(xtalk_intr_t _i_n_t_r)
-
- void
- xtalk_intr_free(xtalk_intr_t _i_n_t_r)
-
-
- AAAArrrrgggguuuummmmeeeennnnttttssss
- _v_h_d_l is the appropriate XIO connection point.
-
- _d_e_s_c is a device descriptor, usually zero.
-
- _l_i_n_e_s specifies one or more of the XIO Interrupt pins connected to the
- card.
-
- _o_w_n_e_r is an appropriate vertex handle to use when printing messages
- about this particular interrupt, and is usually a vertex created
- by the device driver.
-
- _i_n_t_r is the opaque interrupt channel handle
-
- _f_u_n_c is a function to be used for interrupt service
-
- _a_r_g is the parameter to pass to the function when this particular
- interrupt occurs, and is commonly a pointer to a driver-private
- data structure.
-
- _s_e_t_f_u_n_c is a callback function that will be called by the infrastructure
- to set up a new interrupt target widget number, address, or
- vector. It will always be called once, to set the initial
-
-
-
- PPPPaaaaggggeeee 1111
-
-
-
-
-
-
- xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333)))) xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333))))
-
-
-
- assignment; the system may call it again, later, if the interrupt
- needs to be migrated to a different target.
-
- _s_e_t_f_u_n_c__a_r_g
- is an opaque value, owned by the driver, that is stored within
- the interrupt structure and can be retrieved by the driver using
- _x_t_a_l_k__i_n_t_r__s_f_a_r_g__g_e_t().
-
- _t_h_r_e_a_d is reserved for use by the interrupt threads subsystem, and
- should be NULL.
-
-
- DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
- When a device driver wishes to accept interrupt events from a device, the
- system needs to assign a target CPU and allocate a vector number on that
- CPU's XIO interface. The target information is then reported back to the
- driver, which can set up its device to send XIO interrupt packets with
- the proper data to the correct target port and address. Only then can a
- service function be attached to the interrupt channel.
-
- This three-phase handling of the XIO interrupt setup allows several
- things:
-
- +o The service function can be changed (or disconnected entirely)
- without losing any hardware resources and having to reallocate them
- in the process.
-
- +o The interrupt can be retargeted from one processor to another, should
- upper layers of software decide this is necessary.
-
- Since the interrupt delivery mechanism carries the address of the
- interrupt function, it is important to disconnect your interrupts before
- unloading your driver. Your driver will not be auto-loaded when an
- interrupt occurs.
-
- The necessary sequence of calls is as follows:
-
- +o When the device is initially attached, _x_t_a_l_k__i_n_t_r__a_l_l_o_c() should be
- used to establish interrupt connectivity between the device and the
- processor. It is common to call _x_t_a_l_k__i_n_t_r__c_o_n_n_e_c_t() at this time.
-
- +o _x_t_a_l_k__i_n_t_r__c_o_n_n_e_c_t() triggers the first callback to the setfunc so
- the driver can correctly configure its hardware for the target
- processor, XIO port, XIO address, and vector number.
-
- +o If the device driver is automatically unloading, it will be unloaded
- shortly after the attaches are complete. Since the driver text is
- going away, it is important for all interrupts to be disconnected.
- _x_t_a_l_k__i_t_e_r_a_t_e() should be used to call a function with each of the
- driver's connection points, which can then execute the proper
- disconnect calls.
-
-
-
-
- PPPPaaaaggggeeee 2222
-
-
-
-
-
-
- xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333)))) xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333))))
-
-
-
- +o When the device driver is reloaded, its _p_f_xinit() entry point is
- called. The device driver should again use _x_t_a_l_k__i_t_e_r_a_t_e(), this
- time to call a function that will re-connect interrupts to the new
- address of the service function. No special logic is needed to
- prevent this at the initial load time, since _x_t_a_l_k__i_t_e_r_a_t_e() is a
- no-operation when the device driver is not registered.
-
- +o When the device driver is unregistered, the act of unregistering with
- the XTALK infrastructure will trigger calls to _p_f_xdetach() which
- should disconnect all interrupt service.
-
-
- AAAAlllltttteeeerrrrnnnnaaaatttteeee SSSScccceeeennnnaaaarrrriiiioooo
- Some devices may not require interrupt service when they are not open.
- Leaving an interrupt allocated but not connected will keep it disabled,
- possibly reducing impact on the system from devices that may interrupt
- when there is no interest from the driver in actually performing any
- services.
-
- If this is true, then the scenario above may be somewhat simplified:
-
- +o If interrupts are required as part of setting up the device in
- _p_f_xattach(), then they can be connected, then disconnected before
- _p_f_xattach() returns.
-
- +o Since interrupts are not active when the device is closed,
- _p_f_xunload() and _p_f_xdetach() do not need to worry about disconnecting
- the interrupt services, and _p_f_xinit() does not need to worry about
- reconnecting them. Instead, _p_f_xopen() would connect the interrupt on
- first open, and _p_f_xclose() would disconnect the interrupt on last
- close.
-
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
- Here is a simple example of how an XIO device driver might get interrupt
- service started.
-
- xiofoo_attach(vertex_hdl_t xconn_vhdl)
- {
- xtalk_intr_t intr;
- struct xiofoo_regs *xiofoo_regs;
-
- ...
- /* This driver uses both line A and line B,
- * and wants to route both to the same
- * service function.
- */
- intr = xtalk_intr_alloc(xconn_vhdl, 0, xiofoo_vhdl);
-
- /* Arrange for the "soft" pointer to
- * be the parameter for the interrupt,
- * and for the device registers themselves
-
-
-
- PPPPaaaaggggeeee 3333
-
-
-
-
-
-
- xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333)))) xxxxttttaaaallllkkkk____iiiinnnnttttrrrr((((DDDD3333))))
-
-
-
- * to be the parameter for the setfunc()
- * call.
- */
- xtalk_intr_connect(
- intr,
- xiofoo_intr,
- (intr_arg_t)xiofoo_soft,
- xiofoo_intr_setfunc,
- (void *)xiofoo_regs,
- (void *)0);
- ...
- }
-
- static void
- xiofoo_intr_setfunc(xtalk_intr_t intr)
- {
- xwidgetnum_t targ = xtalk_intr_target_get(intr);
- iopaddr_t addr = xtalk_intr_addr_get(intr);
- xtalk_intr_vector_t vect = xtalk_intr_vector_get(intr);
- struct xiofoo_regs *fooregs;
-
- fooregs = (struct xiofoo_regs *)
- xtalk_intr_sfarg_get(intr);
-
- fooregs->control &= FOOREGS_INT_ENABLE;
- fooregs->intr_port = targ;
- fooregs->intr_addr = addr;
- fooregs->intr_vect = vect;
- fooregs->control |= FOOREGS_INT_ENABLE;
- }
-
-
- /
-
-
- SSSSEEEEEEEE AAAALLLLSSSSOOOO
- xtalk(D3), xtalk_dma(D3), xtalk_error(D3), xtalk_get(D3), xtalk_pio(D3).
-
-
- DDDDIIIIAAAAGGGGNNNNOOOOSSSSTTTTIIIICCCCSSSS
- _x_t_a_l_k__i_n_t_r__a_l_l_o_c() will return a null value if it can not allocate
- memory.
-
- _x_t_a_l_k__i_n_t_r__c_o_n_n_e_c_t() will return a zero for success, or a negative value
- on failure. Since the channel is preallocated, the only interesting
- failure is the attempt to use a null interrupt cookie value.
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 4444
-
-
-
-